#include <iomanip>
#include <iostream>
#include <openssl/evp.h>
#include <sstream>
#include <string>
#include <vector>

using namespace std;

// 16进制转字节数组
string hexToBytes(const string& hex)
{
    string bytes;
    for (size_t i = 0; i < hex.length(); i += 2) {
        string byteString = hex.substr(i, 2);
        unsigned char byte = (unsigned char)strtol(byteString.c_str(), nullptr, 16);
        bytes += byte;
    }
    return bytes;
}

// 解密函数
string aes_decrypt(const string& ciphertext, const string& key, const string& iv)
{
    vector<unsigned char> plaintext(ciphertext.size() + EVP_MAX_BLOCK_LENGTH);
    int len;
    int plaintext_len;

    EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
    if (!ctx)
        throw runtime_error("无法创建解密上下文");

    if (1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, (const unsigned char*)key.data(), (const unsigned char*)iv.data())) {
        EVP_CIPHER_CTX_free(ctx);
        throw runtime_error("解密初始化失败");
    }

    if (1 != EVP_DecryptUpdate(ctx, plaintext.data(), &len, (const unsigned char*)ciphertext.data(), ciphertext.size())) {
        EVP_CIPHER_CTX_free(ctx);
        throw runtime_error("解密过程出错");
    }
    plaintext_len = len;

    if (1 != EVP_DecryptFinal_ex(ctx, plaintext.data() + len, &len)) {
        EVP_CIPHER_CTX_free(ctx);
        throw runtime_error("解密失败, 可能是密钥或IV不正确");
    }
    plaintext_len += len;

    EVP_CIPHER_CTX_free(ctx);
    plaintext.resize(plaintext_len);
    return string(plaintext.begin(), plaintext.end());
}

int main()
{
    setlocale(LC_ALL, "");

    string hex_cipher;
    string key = "peacepeacebutthereisnopeace"; // 256-bit key

    while (true) {
        cout << "请输入IV(16字节):";
        string hex_iv;
        getline(cin, hex_iv);
        string iv = hexToBytes(hex_iv);
        cout << "请输入密文:";
        getline(cin, hex_cipher);
        try {
            string ciphertext = hexToBytes(hex_cipher);
            string decrypted = aes_decrypt(ciphertext, key, iv);
            cout << "解密后的文本:" << decrypted << endl;
        } catch (const exception& e) {
            cerr << "解密失败:" << e.what() << endl;
        }
    }

    return 0;
}
